<!DOCTYPE html>
<!--
     SPDX-License-Identifier: CC-BY-SA-4.0
     SPDX-FileCopyrightText: 2020 seL4 Project a Series of LF Projects, LLC.
-->
<!-- Page last generated 2025-02-20 03:16:15 +0000 -->
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Elfloader | seL4 docs</title>

    <!-- Our stylesheet and theme stylesheet.  Contains bootstrap. -->
    <link rel="stylesheet" href="/assets/css/style.css" type="text/css">
    <!-- Font awesome -->
    <link href="https://use.fontawesome.com/releases/v5.0.8/css/all.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
    <!-- Pygments syntax highlighting  -->
    <link rel="stylesheet" href="/assets/css/highlighting/trac.css" type="text/css">
    <link rel="icon" type="image/x-icon" href="/assets/favicon.ico"><script defer data-domain="docs.sel4.systems"
	    src="https://analytics.sel4.systems/js/script.js"></script></head>

  <body class="container-fluid">

    



<header>
  <ul class="row menu">
    <li class="col-xs-12 col-md-2" >
            <a href="https://sel4.systems" class="skip-icon">
              <img class="img-responsive" src="/assets/logo-text-white.svg" alt="seL4 logo" />
            </a>
    </li>
    <li class="col-xs-12 col-md-10 menu">
      <nav aria-label="Banner links">
        <h2><a href="/Resources" />Resources</h2>
        <h2><a href="/processes" />Contributing</a></h2>
        <h2><a href="/projects" />Projects</h2>
        <h2><a href="/Tutorials" />Tutorials</h2>
        <iframe title="DuckDuckGo search bar" src="https://duckduckgo.com/search.html?site=docs.sel4.systems&prefill=Search%20sel4.systems" style="overflow:hidden;margin-bottom:10px; padding:0;height:40px;float:right;border-width: 0px"></iframe>
      </nav>
    </li>
  </ul>
  <div class="clear"></div>
  
<div class="breadcrumbs bootstrap hidden-sm-down">
  <nav class="sel-breadcrumb" aria-label="Breadcrumb" >
    <ol class=" list-unstyled" vocab="http://schema.org/" typeof="BreadcrumbList">
      
      
        

        

        <li class="breadcrumb-item" property="itemListElement" typeof="ListItem">
            <a property="item" typeof="WebPage" href="/">
              <span property="name"><b>seL4 Docs</b></span>
            </a>
            <meta property="position" content="1" />
        </li>
      
        

        

        <li class="breadcrumb-item" property="itemListElement" typeof="ListItem">
            <a property="item" typeof="WebPage" href="/projects/">
              <span property="name"><b>Projects</b></span>
            </a>
            <meta property="position" content="2" />
        </li>
      
        

        
          <li class="breadcrumb-item" property="itemListElement" typeof="ListItem">
            <span property="name">Elfloader</span>
            <meta property="position" content="3" /></li>
          
    </ol>
  </nav>
  <nav class="sel-version" aria-label="Current Versions">
    <ol class="list-unstyled">
      <li class="list-unstyled text-right" style="margin-left:auto; padding:0rem 0rem;">
        Current versions:</li>
      <li class="list-unstyled text-right">
      <a href="/releases/sel4/13.0.0"><b>seL4-13.0.0</b></a></li>
      <li class="list-unstyled text-right">
      <a href="/releases/microkit/1.4.1"><b>microkit-1.4.1</b></a></li>
      <li class="list-unstyled text-right">
      <a href="/releases/camkes/camkes-3.11.0"><b>camkes-3.11.0</b></a></li>
      <li class="list-unstyled text-right">
      <a href="/releases/capdl/0.3.0"><b>capDL-0.3.0</b></a></li>
      </ol>
  </nav>
  <div class='clear'></div>
</div>


</header>

    <main>
      <div class="row">
  <div class="hidden-xs col-sm-4 col-md-3 col-lg-2">
    


<div class="sidebar">















    <ul class="nav nav-sidebar">
  
    
    

    
        <li class="">
            <a class="" href="/projects/sel4/">seL4</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/l4v/">L4.verified</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/camkes/">CAmkES</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/capdl/">CapDL</a>
        </li>
  
    
    

    
        <li class="active">
            <a class="" href="/projects/elfloader/">Elfloader</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/buildsystem/">seL4 Buildsystem</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/user_libs/">user_libs</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/sel4runtime/">The seL4 run-time</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/sel4webserver/">seL4webserver</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/sel4-tutorials/">seL4 tutorials</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/sel4bench/">sel4bench</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/sel4test/">seL4Test</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/virtualization/">Virtualization</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/camkes-vm/">camkes-vm</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/dockerfiles/">Dockerfiles</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/docsite/">seL4 Documentation website</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/sel4_tools/">seL4_tools</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/microkit/">Microkit</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/hardware_hacks/">Hardware Hacks</a>
        </li>
  
    
    

    
        <li class="">
            <a class="" href="/projects/rust/">Rust</a>
        </li>
  
    </ul>


</div>

  </div>
  <div class="content col-sm-8 col-md-6 col-lg-7 main">
    
<!--
     Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)

     SPDX-License-Identifier: GPL-2.0-only
-->
<h1 id="elfloader">Elfloader</h1>

<p>The elfloader is responsible for preparing the hardware for seL4 on ARM
and RISC-V. It loads the kernel and user image from an embedded CPIO archive,
initialises secondary cores (if SMP is enabled), and sets up an initial set of page
tables for the kernel.</p>

<h2 id="arm">ARM</h2>

<p>On ARM platforms, the elfloader supports being booted in four ways: as a binary image,
as a u-boot uImage, as an ELF file, and as an EFI executable. Each of these methods differs slightly.
It can also provide seL4 with a DTB - either from the bootloader or included in the embedded CPIO archive.</p>

<ol>
  <li>(EFI only) Elfloader is entered at <code class="language-plaintext highlighter-rouge">_gnuefi_start</code> entry point.</li>
  <li>(EFI only) Elfloader relocates itself</li>
  <li>Elfloader <code class="language-plaintext highlighter-rouge">_start</code> is called. This is in <code class="language-plaintext highlighter-rouge">arch-arm/&lt;arch_bitness&gt;/crt0.S</code>.</li>
  <li>Elfloader initialises the <a href="#driver-framework">driver framework</a>, which enables UART/printf.</li>
  <li>Elfloader loads the kernel, user image, and DTB, determining where the kernel needs to be mapped in memory.</li>
  <li>If the kernel window overlaps the elfloader’s code:
    <ul>
      <li>(AArch32 EFI only) the elfloader relocates itself.
  See <code class="language-plaintext highlighter-rouge">relocate_below_kernel</code> for a detailed explanation of the relocation logic.</li>
      <li>(Other platforms) the elfloader aborts.</li>
    </ul>
  </li>
  <li>The elfloader resumes booting. If it relocated itself, it will re-initialise the driver model.</li>
  <li>If the elfloader is in HYP mode but seL4 is not configured to support HYP, it will leave HYP mode.</li>
  <li>The elfloader sets up the initial page tables for the kernel (see <code class="language-plaintext highlighter-rouge">init_hyp_boot_vspace</code> or <code class="language-plaintext highlighter-rouge">init_boot_vspace</code>).</li>
  <li>If SMP is enabled, the elfloader boots all secondary cores.</li>
  <li>The elfloader enables the MMU.</li>
  <li>The elfloader launches seL4, passing information about the user image and the DTB.</li>
</ol>

<h3 id="binary">Binary</h3>

<p>The elfloader expects to be executed with a base address as generated by the <code class="language-plaintext highlighter-rouge">shoehorn</code> utility.
You can determine the correct address for a given image by running</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>aarch64-linux-gnu-objdump -t elfloader/elfloader | grep _text
</code></pre></div></div>
<p>from the kernel build directory. The first field in the output contains the base address.</p>

<p>On aarch64, the elfloader will try and move itself to the right address, however, this will fail
if the load address and the correct address are too close, as the relocation code will be overwritten.</p>

<p>It is also possible to override <code class="language-plaintext highlighter-rouge">shoehorn</code> and hardcode a load address by setting IMAGE_START_ADDR in CMake.</p>

<h3 id="u-boot">U-Boot</h3>

<p>The elfloader can be booted according to the Linux kernel’s booting convention for ARM/ARM64.
The DTB, if provided, will be passed to seL4 (which will then pass it to the root task).</p>

<h3 id="elf">ELF</h3>

<p>The elfloader supports being executed as an ELF image (via <code class="language-plaintext highlighter-rouge">bootelf</code> in U-Boot or similar).</p>

<h3 id="efi">EFI</h3>

<p>The elfloader integrates EFI support based on the <code class="language-plaintext highlighter-rouge">gnu-efi</code> project. It will relocate itself as appropriate,
and supports loading a DTB from the EFI implementation.</p>

<h2 id="risc-v">RISC-V</h2>

<p>The elfloader on RISC-V basically follows the ARM platforms. However, due to the
lack of available platforms, only two ways are currently supported actively:
building it as ELF file or binary image. In both cases the platform must provide
a <a href="https://github.com/riscv/riscv-sbi-doc">SBI</a> implementation, which will be
used by the elfloader for the log output channel and the multicore boot. The
seL4 build system allows building <a href="https://github.com/riscv/opensbi"><code class="language-plaintext highlighter-rouge">OpenSBI</code></a>
with the elfloader as payload. The <a href="https://github.com/riscv/riscv-pk"><code class="language-plaintext highlighter-rouge">bbl</code></a>
Support has been dropped, because it is superseded by <code class="language-plaintext highlighter-rouge">OpenSBI</code>.</p>

<h2 id="driver-framework">Driver framework</h2>

<p>The elfloader provides a driver framework to reduce code duplication between platforms.
Currently the driver framework is only used for UART output, however it is designed with extensibility in mind.
In practice, this is currently only used on ARM, as RISC-V uses SBI for UART, and SBI has no device tree entries.
However, in the future it may become useful on RISC-V.</p>

<p>The driver framework uses a header file containing a list of devices generated by the <code class="language-plaintext highlighter-rouge">hardware_gen.py</code> utility
included in seL4. Currently, this header only includes the UART specified by the <code class="language-plaintext highlighter-rouge">stdout-path</code> property in the DTB.
Each device in the list has a compatible string (<code class="language-plaintext highlighter-rouge">compat</code>), and a list of addresses (<code class="language-plaintext highlighter-rouge">region_bases[]</code>) which correspond to the regions specified
by the <code class="language-plaintext highlighter-rouge">reg</code> property in the DTB.</p>

<p>Each driver in the elfloader has a list of compatible strings, matching those found in the device tree.
For instance, the 8250 UART driver, used on Tegra and TI platforms has the following:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">dtb_match_table</span> <span class="n">uart_8250_matches</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
    <span class="p">{</span> <span class="p">.</span><span class="n">compatible</span> <span class="o">=</span> <span class="s">"nvidia,tegra20-uart"</span> <span class="p">},</span>
    <span class="p">{</span> <span class="p">.</span><span class="n">compatible</span> <span class="o">=</span> <span class="s">"ti,omap3-uart"</span> <span class="p">},</span>
    <span class="p">{</span> <span class="p">.</span><span class="n">compatible</span> <span class="o">=</span> <span class="s">"snps,dw-apb-uart"</span> <span class="p">},</span>
    <span class="p">{</span> <span class="p">.</span><span class="n">compatible</span> <span class="o">=</span> <span class="nb">NULL</span> <span class="cm">/* sentinel */</span> <span class="p">},</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Each driver also has a ‘type’. Currently the only type supported is <code class="language-plaintext highlighter-rouge">DRIVER_UART</code>. The <code class="language-plaintext highlighter-rouge">type</code>
indicates the type of struct that is found in the <code class="language-plaintext highlighter-rouge">ops</code> pointer of each driver object,
and provides type-specific functionality.
(For instance, UART drivers have a <code class="language-plaintext highlighter-rouge">elfloader_uart_ops</code> struct which contains a <code class="language-plaintext highlighter-rouge">putc</code> function).
Finally, drivers also provide an <code class="language-plaintext highlighter-rouge">init</code> function, which is called when the driver is matched with a device,
and can be used to perform device-specific setup (e.g. setting the device as the UART output).</p>

<p>Finally, each driver has a <code class="language-plaintext highlighter-rouge">struct elfloader_driver</code> and a corresponding <code class="language-plaintext highlighter-rouge">ELFLOADER_DRIVER</code> statement.
Taking the 8250 UART driver as an example again:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">elfloader_driver</span> <span class="n">uart_8250</span> <span class="o">=</span> <span class="p">{</span>
    <span class="p">.</span><span class="n">match_table</span> <span class="o">=</span> <span class="n">uart_8250_matches</span><span class="p">,</span>
    <span class="p">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">DRIVER_UART</span><span class="p">,</span>
    <span class="p">.</span><span class="n">init</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">uart_8250_init</span><span class="p">,</span>
    <span class="p">.</span><span class="n">ops</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">uart_8250_ops</span><span class="p">,</span>
<span class="p">};</span>

<span class="n">ELFLOADER_DRIVER</span><span class="p">(</span><span class="n">uart_8250</span><span class="p">);</span>
</code></pre></div></div>

<h4 id="uart">UART</h4>

<p>The driver framework provides a “default” (<code class="language-plaintext highlighter-rouge">__attribute__((weak))</code>) implementation of <code class="language-plaintext highlighter-rouge">plat_console_putchar</code>, which calls
the <code class="language-plaintext highlighter-rouge">putc</code> function for the elfloader device provided to <code class="language-plaintext highlighter-rouge">uart_set_out</code> - discarding all characters
that are given to it before <code class="language-plaintext highlighter-rouge">uart_set_out</code> is called. This can be overridden if you do not wish to use
the driver framework (e.g. for very early debugging).</p>

<h2 id="porting-the-elfloader">Porting the elfloader</h2>

<h3 id="to-arm">To ARM</h3>

<p>Once a kernel port has been started (and a DTB provided), porting the elfloader to a platform is reasonably
straightforward.</p>

<p>Most platform-specific information is extracted from a DTB, including available physical memory ranges. If the
platform uses a UART compatible with another platform, even the UART will work out of the box. In other cases,
it might be necessary to add a new <code class="language-plaintext highlighter-rouge">dtb_match_table</code> entry to an existing driver, or add a new driver
(which is fairly trivial - only the <code class="language-plaintext highlighter-rouge">match_table</code> and <code class="language-plaintext highlighter-rouge">putchar</code> functions from an existing driver would
need to be changed).</p>

<p>An appropriate image type needs to be selected. By default <code class="language-plaintext highlighter-rouge">ElfloaderImage</code> is set to <code class="language-plaintext highlighter-rouge">elf</code>, however,
various platform-specific overrides exist and can be found in <code class="language-plaintext highlighter-rouge">ApplyData61ElfLoaderSettings</code> in this repo, at
<code class="language-plaintext highlighter-rouge">cmake-tool/helpers/application_settings.cmake</code>.</p>

<h3 id="to-risc-v">To RISC-V</h3>

<p>TODO - it seems there’s not actually that much that needs to be done on the elfloader side.</p>

<p><em>File included from <a href="https://github.com/sel4/sel4_tools/blob/master/elfloader-tool/README.md">github repo</a> <a href="https://github.com/sel4/sel4_tools/edit/master/elfloader-tool/README.md">edit</a></em></p>


  </div>







  
    
<div class="sidebar-toc hidden-xs hidden-sm col-md-3 col-lg-3">
    <ul id="toc" class="section-nav">
<li class="toc-entry toc-h2"><a href="#arm">ARM</a>
<ul>
<li class="toc-entry toc-h3"><a href="#binary">Binary</a></li>
<li class="toc-entry toc-h3"><a href="#u-boot">U-Boot</a></li>
<li class="toc-entry toc-h3"><a href="#elf">ELF</a></li>
<li class="toc-entry toc-h3"><a href="#efi">EFI</a></li>
</ul>
</li>
<li class="toc-entry toc-h2"><a href="#risc-v">RISC-V</a></li>
<li class="toc-entry toc-h2"><a href="#driver-framework">Driver framework</a>
<ul>
<li class="toc-entry toc-h4"><a href="#uart">UART</a></li>
</ul>
</li>
<li class="toc-entry toc-h2"><a href="#porting-the-elfloader">Porting the elfloader</a>
<ul>
<li class="toc-entry toc-h3"><a href="#to-arm">To ARM</a></li>
<li class="toc-entry toc-h3"><a href="#to-risc-v">To RISC-V</a></li>
</ul>
</li>
</ul>
</div>

  
  
<div class="sidebar-toc hidden-xs hidden-sm col-md-3 col-lg-3">
  
    <ul class="section-nav">
    	<h2> Elfloader </h2> 
        <li>
          
          <a style=" font-weight: bold; " class="" href="/projects/elfloader/">
            Documentation homepage
          </a>
        </li>

















    
        <h3>Repositories</h3>
    
        <li>
          <a class="" href="https://github.com/seL4/sel4_tools">
            sel4_tools
          </a>
        </li>









  







    
        <h3>Recent Updates</h3>
    
        <li>
          <a style="" href="/updates/elfloader/11.0.x.html">
            seL4 11.0.x-compatible
          </a>
        </li>

    </ul>

</div>


</div>

    </main>
    


<footer class="site-footer">

  <h2 class="footer-heading">seL4 docs</h2>

  <div class="footer-col-wrapper">

    <div class="col-md-2">
      



<ul class="social-media-list">
  <li><a href="https://github.com/sel4"><i class="fab fa-github"></i> <span class="username">sel4</span></a></li><li><a href="https://github.com/sel4proj"><i class="fab fa-github"></i> <span class="username">sel4proj</span></a></li>
</ul>

    </div>

    <div class="col-md-8">
      <ul class="list-unstyled">
        <li>
          This site is for displaying seL4 related documentation.  Pull requests are welcome.
        </li>
        
          <li>
            Site last updated: Fri Feb 7 10:17:38 2025 +1100 ee78c8857c
          </li>
          <li>
                Page last updated: Mon Nov 30 09:25:37 2020 +1100 977ed44f17
          </li>
        
      </ul>
    </div>
    <div class="col-md-2">
<a href="https://github.com/seL4/docs/blob/master/projects/elfloader/index.md">View page on GitHub</a>
      <br />
      <a href="https://github.com/seL4/docs/edit/master/projects/elfloader/index.md">Edit page on GitHub</a>
      <br />
      <a href="/sitemap">Sitemap</a>
    </div>

  </div>

</footer>

  </body>
</html>
